#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/input.h>
#include <sys/types.h>
#include <pwd.h>

// 编译方法：gcc main.c -o keyboard-shortcut

// 可以安装 evtest 软件来找出键盘是哪个设备：sudo pacman -S evtest
// 然后使用root权限运行evtest工具：sudo evtest
// 然后我发现/dev/event4这个设备是我的键盘设备。
// “/dev/input/event*”的事件编号与设备的联系不是固定的，它通常按系统检测到设备的先后顺序安排event文件的编号，
// 这对编写应用程序控制不太方便，我们可以通过“/dev/input/by-id”或“/dev/input/by-path”目录查看具体的硬件设备。
// 例如我通过 ll -h /dev/input/by-path 命令，知道/dev/input/by-path/pci-0000:3a:00.0-usbv2-0:1.2:1.0-event-kbd 是/dev/event4 的软链接，
// 也就是说文件 pci-0000:3a:00.0-usbv2-0:1.2:1.0-event-kbd 就是访问该键盘的事件设备，而且这个文件名与硬件的关系是固定的。
#define EVENT_DEV "/dev/input/by-path/pci-0000:3a:00.0-usbv2-0:1.2:1.0-event-kbd" // 替换为实际的设备文件路径

// 以uid为1000的这个用户运行utools
int run_utools_with_uid_1000()
{

    pid_t pid;
    uid_t user_id = 1000; // 更改为实际存在的非root用户的UID
    struct passwd *pwd = getpwuid(user_id);
    char *username = pwd->pw_name;

    printf("uid=1000的用户是: %s\n", username);

    char command[128];
    snprintf(command, sizeof(command), "sudo -u %s /usr/bin/utools", username);
    printf("command: %s\n", command);

    // 创建子进程
    pid = fork();
    if (pid < 0) {
        perror("Fork failed");
        exit(EXIT_FAILURE);
    }

    if (pid == 0) {
        // 子进程
        // 执行指定程序
        system(command);
    }

    else{
        // 父进程
    }

    return 0;
}

int main()
{
    int fd;
    struct input_event ev;
    ssize_t n;

    const char KEYBOARD_EVENT_DEV_PATH[] = "/dev/input/by-path/pci-0000:3a:00.0-usbv2-0:1.2:1.0-event-kbd";

    // 打开设备文件
    fd = open(KEYBOARD_EVENT_DEV_PATH, O_RDONLY);
    if (fd == -1)
    {
        perror("open");
        exit(EXIT_FAILURE);
    }

    static struct timeval time_of_last_left_alt_key_pressed = {.tv_sec = 0, .tv_usec = 0};

    // 读取并解析输入事件
    while (1)
    {
        n = read(fd, &ev, sizeof(struct input_event));
        if (n == (ssize_t)-1)
        {
            perror("read");
            break;
        }

        // 检查事件类型是否为按键事件
        if (ev.type == EV_KEY)
        {
            // 打印按键信息
            // printf("Time %ld.%06ld, Type %d, Code %d, Value %d\n",  ev.time.tv_sec, ev.time.tv_usec, ev.type, ev.code, ev.value);

            // ev.code用于判断是哪个键
            // ev.value用于判断是按下还是释放
            const int PRESSED = 1, RELEASED = 0, REPEATED = 3;

            if (ev.code == KEY_LEFTALT && ev.value == PRESSED)
            {
                long long duration_in_millisec = (ev.time.tv_sec - time_of_last_left_alt_key_pressed.tv_sec) * 1000LL +
                                                 (ev.time.tv_usec - time_of_last_left_alt_key_pressed.tv_usec) / 1000;
                // 两次按下Alt键的时间间隔小于300毫秒，认定为双击
                if (duration_in_millisec < 300LL)
                {
                    printf("你双击了左侧的Alt键\n");

                    run_utools_with_uid_1000();
                }
                time_of_last_left_alt_key_pressed = ev.time;
            } else if (ev.code != KEY_LEFTALT){
                time_of_last_left_alt_key_pressed.tv_sec = 0;
                time_of_last_left_alt_key_pressed.tv_usec = 0;
            }
        }
    }

    // 关闭设备文件
    close(fd);

    return 0;
}